package puzzleEdit;

import java.util.Random;

import model.MatrixCube;

/**
 * @author      Zalan Czirjak <zaorsz@yahoo.com>
 * @version     2011.0509
 * @since       1.6
 */
public class CubeSlicer {
	/**A kocka amit majd szetszeletelunk. -3dmatrix;*/
	private MatrixCube cube;
	/**A konkavitast garantalo darab forgatasai.*/
	private MatrixCube[] pieces;
	/**A megszerkesztett vagatok.*/
	private MatrixCube[] finalPieces;
	/**A vagatok szama.*/
	private int pieceNum;
	/**Kocka merete.*/
	private int size;
	
	/**
	 * A kocka meretevel inicializalo konstruktor.
	 * @param dim - kocka merete
	 */
	public CubeSlicer(int dim){
		size=dim;
		pieceNum=2*size;
		cube = new MatrixCube(size);
		cube.init();
		//megvaltoztatom a kockaba irhato ertekeket ... vagatok megkulonboztetese miatt
		//cube.setBound(pieceNum+1);
		//vagatreszletek elokeszitese
		kPiacePreparation();
		//vegso vagatok elokeszitese
		piacePreparation();
	}
	
	/**
	 * Elokeszit egy vektor a kocka vagatainak tarolasara.
	 */
	private void piacePreparation() {
		finalPieces = new MatrixCube[pieceNum];
		for(int i=0; i<pieceNum; i++){
			finalPieces[i] = new MatrixCube(size);
			finalPieces[i].init();
		}
	}

	/**
	 * A konkavitashoz szukseges darabok forgatasainak elokeszitese.
	 */
	private void kPiacePreparation(){
		MatrixCube piece = new MatrixCube(size);
		piece.init();
		//konkavitast garantalo darab bealliasa
		piece.setCubeElement(1, 1, 1, 1);
		piece.setCubeElement(1, 1, 2, 1);
		piece.setCubeElement(1, 1, 1, 2);
		//ennek a darabnak az osszes lehetseges forgatasanak legeneralasa
		pieces = new MatrixCube[24];
		pieces = piece.listOfCubeRotations();
	}
	
	public void slice(){
		Random gen = new Random();
		//kivalasztok egy konkav vagatot es az megprobalom beilleszteni a kockaba
		for(int num=0; num<pieceNum; num++){
			while(attempt(num,pieces[gen.nextInt(24)],gen)){}
		}
	}
	/**
	 * A parameterben megjeleno kockareszt megprobaljuk beilleszteni a kocka bizonyos szintjere.
	 * @param id	- hanyadik db. kockareszlet amit beillesztunk
	 * @param part	- maga a kockareszlet
	 * @param gen	- egy random generator ... kesobb kell
	 * @return	true, ha a beillesztes sikeres volt, kulonben false.
	 */
	private boolean attempt(int id, MatrixCube part, Random gen){
		//magassag beallitasa
		//a darabot felteszitjuk a tetejeb
		while(part.shiftCubeUp2()){}
		//annyit nyomjuk le, hogy minden szinten 2 darabka legyen
		int num=(int)id%2;
		while(num!=0&&part.shiftCubeDown2()){}
		
		//akkor megyunk balra, ha generalt szam = 0
		boolean bal=(gen.nextInt(2)==0);
		if(bal){
			//elmegyunk teljesen balra
			while(part.shiftCubeLeft2()){}
			//bejarjuk az adott szintet
			return walk(part);
		}
		else{//ha jobbra megyunk
			while(part.shiftCubeRight2()){}
			//bejarjuk az adott szintet
			return walk(part);
		}
	}
	/**
	 * Bejar egy szintet a kockabol, helyet keresve az adott kockareszenek.
	 * @param part - kockaresz
	 * @return	true, ha kapott egy helyet (akkor be is illeszti), kulonben false.
	 */
	private boolean walk(MatrixCube part){
		//teljesen a kocka vegebe rakjuk
		while(part.shiftCubeForward2()){}
		boolean back=true;
		//majd onnantol kezdve ameddig meg lehet jobbi jobbra, hol elore menve,
		//hol hatra menve megnezzuk a lehetosegeinket.
		do{
			while(back){
				if(part.canAddCubes(part))
					return part.sumCube2(part);
				else
					if(!part.shiftCubeBack2())
						back=false;
			}
			while(!back){
				if(part.canAddCubes(part))
					return part.sumCube2(part);
				else
					if(!part.shiftCubeForward2())
						back=false;
			}
			
		}while(part.shiftCubeRight2());
		return false;
	}
		
	public static void main (String[] args){
		CubeSlicer slicer =new CubeSlicer(3);
		slicer.slice();
		slicer.getCube().printCube();
	}

	public MatrixCube getCube() {
		return cube;
	}
}
